package com.br.cashflowdao.hibernate.dao.factory;

import com.br.cashflowdao.hibernate.dao.AccountDAO;
import com.br.cashflowdao.hibernate.dao.CategoryDAO;
import com.br.cashflowdao.hibernate.dao.CategoryTypeDAO;
import com.br.cashflowdao.hibernate.dao.CreditTransactionDAO;
import com.br.cashflowdao.hibernate.dao.DebitTransactionDAO;
import com.br.cashflowdao.hibernate.dao.GenericDAO;
import com.br.cashflowdao.hibernate.dao.TransferTransactionDAO;

/**
 * This abstract class creates a standalone <code>DAOFactory</code> that returns 
 * managed DAO beans for use in any environment Hibernate has been configured for.
 * <p>
 * Any DAO class that will be used must be defined in this abstract class as abstract methods with
 * <code>protected</code> visibility. No DAO class can be accessed or be visible
 * through this abstract class. No implementation method should be provided here,
 * implementation details are responsability of the subclasses.
 * <p>
 * Any class extending this abstract should override this methods or thrown an
 * <code>UnsupportedOperationException</code> when the method implementation is
 * not available.
 * <p>
 * The following line shows the correct usage of this class and its method:
 * <code>DAOFactory factory = DAOFactory.getInstance(MyDAOFactory.class);
 * <p>
 * Where <code>MyDAOFactory.class</code> is any Factory extending this abstract class.
 * <p>
 *
 * @author Marcel Sena <marcel.sena at marcel.sena@gmail.com>
 * @version 1.0
 * @since 05/01/2009
 */
public abstract class DAOFactory {

    /**
     * Default Constructor
     */
    protected DAOFactory() {}

    /**
     * Factory method for instantiation of DAO factories.
     * <p>
     *
     * @param <code>Class</code> that represents the factory that will be created
     * to manage all DAO factories.
     * @return a <code>DAOFactory</code> responsible to instantiate the DAOs.
     * @throws a <code>RuntimeException</code> if the factory can not be created
     */
    public static DAOFactory getInstance(Class factory) {
        try {
            return (DAOFactory)factory.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(
                            "Couldn't create DAOFactory: "
                            + factory + " "
                            + e.getMessage()
                        );
        }
    }

    // Declare DAO interfaces below

    /**
     * Factory method which returns a new instance of the <code>GenericDAO</code>.
     * <p>
     *
     * @return a new <code>GenericDAO</code> object
     */
    public abstract GenericDAO getGenericDAO();

    /**
     * Factory method which returns a new instance of the <code>AccountDAO</code>.
     * <p>
     *
     * @return a new <code>AccountDAO</code> object
     */
    public abstract AccountDAO getAccountDAO();

    /**
     * Factory method which returns a new instance of the <code>CategoryDAO</code>.
     * <p>
     *
     * @return a new <code>CategoryDAO</code> object
     */
    public abstract CategoryDAO getCategoryDAO();

    /**
     * Factory method which returns a new instance of the <code>CreditTransactionDAO</code>.
     * <p>
     *
     * @return a new <code>CreditTransactionDAO</code> object
     */
    public abstract CreditTransactionDAO getCreditTransactionDAO();

    /**
     * Factory method which returns a new instance of the <code>DebitTransactionDAO</code>.
     * <p>
     *
     * @return a new <code>DebitTransactionDAO</code> object
     */
    public abstract DebitTransactionDAO getDebitTransactionDAO();

    /**
     * Factory method which returns a new instance of the <code>TransferTransactionDAO</code>.
     * <p>
     *
     * @return a new <code>TransferTransactionDAO</code> object
     */
    public abstract TransferTransactionDAO getTransferTransactionDAO();

    /**
     * Factory method which returns a new instance of the <code>CategoryTypeDAO</code>.
     * <p>
     *
     * @return a new <code>CategoryTypeDAO</code> object
     */
    public abstract CategoryTypeDAO getCategoryTypeDAO();
}